package com.example.sample.activity;

import android.app.Activity;
import android.content.Intent;
import android.net.VpnService;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.example.sample.vpn.MyVpnService;
import com.example.sample.vpn.PacketForwarder;
import com.example.sample.vpn.VpnNative;

import net.liteheaven.xblib.common.rom.ApkUtil;
import net.liteheaven.xblib.common.rom.ShellUtil;
import net.liteheaven.xfirewall.R;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

public class VpnActivity extends Activity {

    // 界面
    private Button mBtnStartVpn;
    private Button mBtnStartForwarder;
    private Button mBtnClear;
    private Button mBtnSendUdp;
    private Button mBtnSendTcp;
    private Button mBtnTcpListen;
    private Button mBtnUdpListen;
    private TextView mTvIP;
    private TextView mTvPid;
    private TextView mTvLog;
    private EditText mEtDstUdpIp;
    private EditText mEtDstTcpIp;
    private EditText mEtLocalUdpPort;
    private EditText mEtLocalTcpPort;

    private Handler mMainHanlder;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_vpn);

        mMainHanlder = new Handler();

        mEtLocalUdpPort = (EditText)findViewById(R.id.etLocalUdpPort);
        mEtLocalTcpPort = (EditText)findViewById(R.id.etLocalTcpPort);
        mEtDstUdpIp = (EditText)findViewById(R.id.etDstUdpIp);
        mEtDstTcpIp = (EditText)findViewById(R.id.etDstTcpIp);
        mBtnStartVpn = (Button)findViewById(R.id.btnStartVpn);
        mBtnStartVpn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                vpnPrepare();
            }
        });
        mBtnStartForwarder = (Button)findViewById(R.id.btnStartForwarder);
        mBtnStartForwarder.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 启动转发线程
                VpnNative.startForwarder(PacketForwarder.TCP_FORWARD_PORT);
            }
        });
        mBtnClear = (Button)findViewById(R.id.btnClear);
        mBtnClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mTvLog.setText("");
            }
        });
        mBtnUdpListen = (Button)findViewById(R.id.btnUdpListen);
        mBtnUdpListen.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                udpListen();
            }
        });
        mBtnTcpListen = (Button)findViewById(R.id.btnTcpListen);
        mBtnTcpListen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tcpListen();
            }
        });
        mBtnSendTcp = (Button)findViewById(R.id.btnSendTcp);
        mBtnSendTcp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendTcp("9874pi");
            }
        });

        mBtnSendUdp = (Button)findViewById(R.id.btnSendUdp);
        mBtnSendUdp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendUdp("1234ab");
            }
        });

        mTvIP = (TextView)findViewById(R.id.tvIP);
        String ip = getIPAddress(true);
        mTvIP.setText("本地IP：" +ip);

        mTvPid = (TextView)findViewById(R.id.tvPid);
        int pid = ApkUtil.getProcessId(getApplicationContext(), "com.example.sample");
        int uid = ShellUtil.getUid(pid);
        mTvPid.setText("PID="+pid + " UID="+uid);

        mTvLog = (TextView)findViewById(R.id.tvLog);

        // test
        StringBuffer execResult = ShellUtil.execCommand("cat /proc/net/tcp");
        String showit = getIp(execResult.toString());
        //appendLog(showit);

        // 指定日志回调
        PacketForwarder pt = PacketForwarder.getInstance();
        pt.setListener(new PacketForwarder.ForwardListener() {
            @Override
            public void onLog(final String log) {
                mMainHanlder.post(new Runnable() {
                    @Override
                    public void run() {
                        appendLog(log);
                    }
                });
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        PacketForwarder pt = PacketForwarder.getInstance();
        pt.setListener(null);
    }

    private void vpnPrepare(){
        Intent intent = VpnService.prepare(getApplicationContext());
        if (intent != null) {
            startActivityForResult(intent, 0);
        } else {
            onActivityResult(0, RESULT_OK, null);
        }
    }

    private void udpListen(){
        PacketForwarder pt = PacketForwarder.getInstance();
        String port = mEtLocalUdpPort.getText().toString();
        int port_val = Integer.valueOf(port);
        pt.startListenUdp(port_val);
    }

    private void tcpListen(){
        PacketForwarder pt = PacketForwarder.getInstance();
        String port = mEtLocalTcpPort.getText().toString();
        int port_val = Integer.valueOf(port);
        pt.startListenTcp(port_val);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            Intent intent = new Intent(this, MyVpnService.class);
            startService(intent);
        }
    }

    private void sendUdp(final String content){

        final String ip = mEtDstUdpIp.getText().toString();
        AsyncTask at = new AsyncTask() {
            @Override
            protected Object doInBackground(Object[] params) {
                PacketForwarder.sendUdp(ip, PacketForwarder.UDP_GAME_SERVER_PORT ,content);
                return null;
            }
        };
        at.execute();
    }

    private void sendTcp(final String content){
        final String ip = mEtDstTcpIp.getText().toString();
        AsyncTask at = new AsyncTask() {
            @Override
            protected Object doInBackground(Object[] params) {
                int port = PacketForwarder.TCP_GAME_SERVER_PORT;
                PacketForwarder.sendTcp(ip, port, content);
                return null;
            }
        };
        at.execute();
    }

    private void appendLog(String log){
        mTvLog.append(log);
        mTvLog.append("\n");
    }

    private String getIp(String src){
        String [] line = src.split("\n");
        return line[1];
    }

    /**
     * 获取IP地址
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.INTERNET"/>}</p>
     *
     * @param useIPv4 是否用IPv4
     * @return IP地址
     */
    public static String getIPAddress(boolean useIPv4) {
        try {
            for (Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces(); nis.hasMoreElements(); ) {
                NetworkInterface ni = nis.nextElement();
                // 防止小米手机返回10.0.2.15
                if (!ni.isUp()) continue;
                for (Enumeration<InetAddress> addresses = ni.getInetAddresses(); addresses.hasMoreElements(); ) {
                    InetAddress inetAddress = addresses.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                        String hostAddress = inetAddress.getHostAddress();
                        boolean isIPv4 = hostAddress.indexOf(':') < 0;
                        if (useIPv4) {
                            if (isIPv4) return hostAddress;
                        } else {
                            if (!isIPv4) {
                                int index = hostAddress.indexOf('%');
                                return index < 0 ? hostAddress.toUpperCase() : hostAddress.substring(0, index).toUpperCase();
                            }
                        }
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return null;
    }
}
